﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace VisualPureBasicIDE.FormDesigner.Implementations
{
    internal class EventBindingService : IEventBindingService
    {
        private readonly Designer _host;

        public EventBindingService(Designer myHost)
        {
            _host = myHost;
        }

        #region IEventBindingService Members

        public string CreateUniqueMethodName(IComponent component,
                                             EventDescriptor e)
        {
            if (component == null) throw new ArgumentNullException("component");
            if (e == null) throw new ArgumentNullException("e");
            return component.Site.Name + "_" + e.DisplayName;
        }

        public ICollection GetCompatibleMethods(EventDescriptor e)
        {
            if (e == null) throw new ArgumentNullException("e");
            return new[] {e.DisplayName};
        }

        public EventDescriptor GetEvent(PropertyDescriptor property)
        {
            if (property == null)
                throw new ArgumentNullException("property");

            var eventPropDescriptor = property as EventPropertyDescriptor;

            return eventPropDescriptor == null ? null : eventPropDescriptor.InternalEventDescriptor;
        }

        public PropertyDescriptorCollection GetEventProperties(
            EventDescriptorCollection events)
        {
            if (events == null)
                throw new ArgumentNullException("events");

            var properties = new List<PropertyDescriptor>();
            foreach (EventDescriptor eventDescriptor in events)
                properties.Add(((IEventBindingService) this).GetEventProperty(eventDescriptor));

            return new PropertyDescriptorCollection(properties.ToArray());
        }

        public PropertyDescriptor GetEventProperty(EventDescriptor e)
        {
            if (e == null)
                throw new ArgumentNullException("e");

            return new EventPropertyDescriptor(e);
        }

        public bool ShowCode(IComponent component, EventDescriptor e)
        {
            // TODO: Implement showing code here
            return false;
        }

        public bool ShowCode(int lineNumber)
        {
            return false;
        }

        public bool ShowCode()
        {
            return false;
        }

        #endregion
    }

    internal class EventPropertyDescriptor : PropertyDescriptor
    {
        private readonly EventDescriptor _eventDescriptor;

        public EventPropertyDescriptor(EventDescriptor eventDescriptor)
            : base(eventDescriptor)
        {
            if (eventDescriptor == null)
                throw new ArgumentNullException("eventDescriptor");
            _eventDescriptor = eventDescriptor;
        }

        public override Type ComponentType
        {
            get { return _eventDescriptor.ComponentType; }
        }

        public override bool IsReadOnly
        {
            get { return false; }
        }

        public override Type PropertyType
        {
            get { return _eventDescriptor.EventType; }
        }

        public override TypeConverter Converter
        {
            get { return TypeDescriptor.GetConverter(String.Empty); }
        }

        internal EventDescriptor InternalEventDescriptor
        {
            get { return _eventDescriptor; }
        }

        public override bool CanResetValue(object component)
        {
            return true;
        }

        public override void ResetValue(object component)
        {
            SetValue(component, null);
        }

        public override object GetValue(object component)
        {
            if (component is IComponent && ((IComponent) component).Site != null)
            {
                var dictionary =
                    ((IComponent) component).Site.GetService(typeof (IDictionaryService)) as IDictionaryService;
                if (dictionary != null)
                    return dictionary.GetValue(base.Name);
            }
            return null;
        }

        public override void SetValue(object component, object value)
        {
            if (component is IComponent && ((IComponent) component).Site != null)
            {
                var dictionary =
                    ((IComponent) component).Site.GetService(typeof (IDictionaryService)) as IDictionaryService;
                if (dictionary != null)
                    dictionary.SetValue(base.Name, value);
            }
        }

        public override bool ShouldSerializeValue(object component)
        {
            return GetValue(component) != null;
        }
    }
}